/**
 * MCU 系统滴答时钟适配 API 头文件
 * Copyright (c) 2021 深圳市智辰科技有限公司
 * All rights reserved.
 */

#ifndef _SYS_CLOCK_H_
#define _SYS_CLOCK_H_

#include "stdc.h"
#include "std_err.h"

#ifdef __cplusplus
extern "C" {
#endif


// ============================================================================
// 毫秒定时器: 使用系统自带的时钟 system_get_curr_time()
// system_get_curr_time() 最大计数为 0x33333330(858993456) ms = 9.94 天
#define MCU_SYSTEM_MS_MAX 858993456

/// 获取当前 ms 数
uint32_t mcu_get_ms(void);
/// 已经花费的 ms 数
uint32_t mcu_elapsed_ms(uint32_t old);
/// 延时 ms
void mcu_delay_ms(uint32_t num);

// ============================================================================
// 系统滴答定时器(使用TIMER0)
#define PCB_SYSTICK_TIMER TIMER0
#define PCB_SYSTICK_TIMER_IRQn (TIMER0_IRQn)

/// 初始化系统滴答定时器
/// 每个时钟滴答时间为一个 CPU 时钟周期
void mcu_systick_timer_init(void);
/// 获取当前 tick 数
uint32_t mcu_get_systick(void);

/// 获取当前 us 数
uint32_t mcu_get_us(void);
/// 已经花费的 us 数
uint32_t mcu_elapsed_us(uint32_t old);
/// us 重新计时
/// @retimer [in] 稍早前的一个 us 时刻；[out] 当前 us 时刻
/// @return 已经过去的 us 数
uint32_t mcu_retiming_us(uint32_t *retimer);
/// 延时 us (小于10us则延时10us)
void mcu_delay_us(uint32_t num);

// ============================================================================
// 微秒定时器(使用TIMER1)
#define PCB_US_TIMER TIMER1
#define PCB_US_TIMER_IRQn (TIMER1_IRQn)

/// 微秒定时器回调函数
/// !!! 注意：此回调函数是在中断中执行的 !!!
typedef void (*mcu_ustimer_handler_t)(void *cookie);

/// 微秒定时器启动
/// @param interval 间隔时间/周期(us)。48M/MAX = 349520 us, 24M/MAX = 699040 us, 12M/MAX = 1398080 us, 6M/MAX = 2796160 us
/// @param repeat 重复次数。= MAXU32 时表示永远循环。
/// @param handler 回调函数，每个周期回调一次
/// @param cookie 回调函数 cookie
std_err_t mcu_ustimer_run_every(uint32_t interval, uint32_t repeat, mcu_ustimer_handler_t handler, void *cookie);

/// 微秒定时器停止
void mcu_ustimer_stop(void);

/// 测试
/// 如：mcu_ustimer_test(1365, 10);
void mcu_ustimer_test(uint32_t interval, uint32_t repeat);

// ============================================================================
// RTC 时钟最大计数值(uint32_t 可以表示 136 年多)
#define MCU_RTC_COUNT_MAX MAXU32

/// 加载基准时间回调函数原型(要存储在 Flash 中)
typedef uint32_t (*FUNC_loadBaseTime)(void);
/// 保存基准时间回调函数原型(要存储在 Flash 中)
typedef void (*FUNC_saveBaseTime)(uint32_t basetime);

/// 获得当前 PMU/RTC 时钟频率
uint32_t mcu_get_pmu_clk_freq(void);

/// 初始化 RTC (会自动判断 RTC 是否已经初始化，如果已经初始化，则不会再初始化，以防时间丢失)
/// @param loadBaseTime 加载基准时间回调函数
/// @param saveBaseTime 保存基准时间回调函数
void mcu_rtc_init(FUNC_loadBaseTime loadBaseTime, FUNC_saveBaseTime saveBaseTime);
/// 获取 RTC 时钟时间戳
uint32_t mcu_get_clock(void);
/// 设置 RTC 时钟时间戳
void mcu_set_clock(uint32_t timestamp);
/// 计算距离指定时间戳过去了多少秒
uint32_t mcu_elapsed_second(uint32_t timestamp);
// 检查、更新 RTC 计数器，并启动 RTC Alarm 定时器，以便在 RTC 计数溢出之前进行再次更新
void mcu_rtc_rearm_updater(void);


#ifdef __cplusplus
}
#endif

#endif // _SYS_CLOCK_H_
